#include <stdio.h>
#include <sharp-rng.h>

/*
struct sharp_rng_s {
    int state[SHARP_RNG_STATES];
    int idx;
};
*/

static sharp_rng internalRNG;

void sharp_rng_init(void){
    sharp_rng_init_r(&internalRNG);
}

void sharp_rng_init_r(sharp_rng *rng){
    FILE *f;

    rng->idx = 0;
    f = fopen(SHARP_RNG_RANDFILE, "r");
    fread(&(rng->state), 4, SHARP_RNG_STATES, f);
    fclose(f);
}

int sharp_rng_get_int(void){
    return sharp_rng_get_int_r(&internalRNG);
}

int sharp_rng_get_int_r(sharp_rng *rng){
    int idx;

    idx = rng->idx;
    rng->state[idx] *= 0x481633;
    rng->state[idx] += 0xCDAA7F9;
    rng->state[idx] &= 0xFFFFFFFF;
    rng->idx++;
    rng->idx %= SHARP_RNG_STATES;
    return rng->state[idx-1] ^ rng->state[idx] ^ rng->state[idx+1];
}

int sharp_rng_get_range(int min, int max){
    return sharp_rng_get_range_r(&internalRNG, min, max);
}

int sharp_rng_get_range_r(sharp_rng *rng, int min, int max){
    return (((unsigned int)sharp_rng_get_int_r(rng))%(max-min+1)) + min;
}

float sharp_rng_get_float(void){
    return sharp_rng_get_float_r(&internalRNG);
}

float sharp_rng_get_float_r(sharp_rng *rng){
    return (float)((unsigned int)sharp_rng_get_int_r(rng)%65536)/65536.0;
}

void sharp_rng_get_string(char *dest, int size){
    sharp_rng_get_string_r(&internalRNG, dest, size);
}

void sharp_rng_get_string_r(sharp_rng *rng, char *dest, int size){
    int i;

    for(i = 0; i < size; i++){
        dest[i] = sharp_rng_get_range_r(rng, (int)' ', (int)'~');
    }
}
